﻿using System;
using System.Collections.Generic;
using System.Text;
using Common.Utilities.TextMatch;

namespace Workflows.Components.TextMining.Clustering
{
    /// <summary>
    /// 
    /// </summary>
    public class TermSimilarityMatrix
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="terms"></param>
        /// <returns></returns>
        public static Dictionary<int, Dictionary<int, double>> BuildTermDistanceMatrixUsingNgram(
            List<Term> terms)
        {
            Dictionary<int, Dictionary<int, double>> termSimilarityMatrix =
                new Dictionary<int, Dictionary<int, double>>();
            for(int i=0;i<terms.Count;i++)
            {
                string txt1 = terms[i].Phrase;
                Dictionary<int,double> similarities=new Dictionary<int, double>();
                for(int k=0;k<terms.Count;k++)
                {
                    string txt2 = terms[k].Phrase;
                    similarities.Add(terms[k].TermID, NGramUtil.ComputeNGramSimilarity(txt1,txt2,4));
                }
                termSimilarityMatrix.Add(terms[i].TermID,similarities);
            }
            return termSimilarityMatrix;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="termFreqs1"></param>
        /// <param name="termFreqs2"></param>
        /// <returns></returns>
        public static Dictionary<int,Dictionary<int,double>> BuildTermDistanceMatrixUsingNgram(
            Dictionary<int,DocTermFreq> termFreqs1, Dictionary<int,DocTermFreq> termFreqs2)
        {
            List<Term> terms=new List<Term>();
            List<int> unionTermIDs=new List<int>();
            foreach(int termID in termFreqs1.Keys)
            {
                Term term = new Term();
                term.TermID = termID;
                term.Phrase = termFreqs1[termID].Phrase;
                term.Weight = termFreqs1[termID].Weight;
                terms.Add(term);
                unionTermIDs.Add(termID);
            }
            foreach(int termID in termFreqs2.Keys)
            {
                if(!unionTermIDs.Contains(termID))
                {
                    Term term = new Term();
                    term.TermID = termID;
                    term.Phrase = termFreqs2[termID].Phrase;
                    term.Weight = termFreqs2[termID].Weight;
                    terms.Add(term);
                }
            }

            return TermSimilarityMatrix.BuildTermDistanceMatrixUsingNgram(terms);
        }

        /// <summary>
        /// root word -> list of term ids
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string,List<int>> BuildTermInflectionalStemmingMappings(List<Term> terms)
        {
            InflectionalStemmer stemmer=new InflectionalStemmer(); 
            Dictionary<string,List<int>> termStemmings=new Dictionary<string, List<int>>();
            foreach(Term term in terms)
            {
                string[] words = term.Phrase.Split(new char[]{' '});
                foreach(string word in words)
                {
                    string root = stemmer.StemTerm(word).ToLower();
                    if(termStemmings.ContainsKey(root))
                    {
                        List<int> termIDs = termStemmings[root];
                        if(!termIDs.Contains(term.TermID))
                            termIDs.Add(term.TermID);
                        termStemmings[root] = termIDs;
                    }
                    else
                    {
                        List<int> termIDs=new List<int>();
                        termIDs.Add(term.TermID);
                        termStemmings.Add(root,termIDs);
                    }
                }
            }

            return termStemmings;
        }

        /// <summary>
        /// root word -> list of term ids
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, List<int>> BuildTermPorterStemmingMappings(List<Term> terms)
        {
            PorterStemmer stemmer = new PorterStemmer();
            Dictionary<string, List<int>> termStemmings = new Dictionary<string, List<int>>();
            foreach (Term term in terms)
            {
                string[] words = term.Phrase.Split(new char[] { ' ' });
                foreach (string word in words)
                {
                    string root = stemmer.StemTerm(word).ToLower();
                    if (termStemmings.ContainsKey(root))
                    {
                        List<int> termIDs = termStemmings[root];
                        if (!termIDs.Contains(term.TermID))
                            termIDs.Add(term.TermID);
                        termStemmings[root] = termIDs;
                    }
                    else
                    {
                        List<int> termIDs = new List<int>();
                        termIDs.Add(term.TermID);
                        termStemmings.Add(root, termIDs);
                    }
                }
            }

            return termStemmings;
        }

    }
}
